package com.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.domain.*;
import com.example.dto.LibraryAddDTO;
import com.example.dto.LibraryCloseDTO;
import com.example.dto.LibraryUpdateDTO;
import com.example.exception.BusinessException;
import com.example.mapper.*;
import com.example.service.LibraryService;
import com.example.util.Result;
import com.example.vo.GetLibraryVO;
import com.example.vo.RoomVO;
import com.example.vo.LibraryTreeVO;
import com.example.vo.RoomTreeVO;
import com.example.vo.BookshelfTreeVO;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author HP
* @description 针对表【library】的数据库操作Service实现
* @createDate 2025-08-24 13:42:54
*/
@Service
public class LibraryServiceImpl extends ServiceImpl<LibraryMapper, Library>
    implements LibraryService{

    @Resource
    private LibraryMapper libraryMapper;
    @Resource
    private RoomMapper roomMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private BookshelfMapper bookshelfMapper;
    @Autowired
    private BookMapper bookMapper;

    @Override
    public Result getLibraries() {
        List<Library> libraries = libraryMapper.selectList(null);
        List<GetLibraryVO> librariesVO = libraries.stream().map(library -> {
            String managerName = userMapper.selectById(library.getManagerId()).getUsername();
            GetLibraryVO libraryVO = new GetLibraryVO();
            BeanUtils.copyProperties(library, libraryVO);
            libraryVO.setManagerName(managerName);
            return libraryVO;
        }).toList();
        return Result.success(librariesVO);
    }

    @Override
    public Result getLibraryRooms(Long libraryId) {
        QueryWrapper<Room> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("library_id", libraryId);
        List<Room> libraryRooms = roomMapper.selectList(queryWrapper);
        String libraryName = libraryMapper.selectById(libraryId).getName();
        List<RoomVO> libraryRoomsVO = libraryRooms.stream().map(room -> {
            RoomVO roomVO = new RoomVO();
            BeanUtils.copyProperties(room, roomVO);
            roomVO.setLibraryName(libraryName);
            return roomVO;
        }).toList();

        return Result.success(libraryRoomsVO);
    }

    @Override
    public Result addLibrary(LibraryAddDTO libraryAddDTO) {
        // 先检查库存
        QueryWrapper<Library> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", libraryAddDTO.getName());
        Library isExist = libraryMapper.selectOne(queryWrapper);
        if (isExist != null) {
            throw new BusinessException("该图书馆已存在");
        }
        if(libraryMapper.selectOne(new QueryWrapper<Library>().eq("address", libraryAddDTO.getAddress())) != null) {
            throw new BusinessException("该地址已存在图书馆");
        }
        if(libraryAddDTO.getManagerId() == null){
            throw new BusinessException("请选择馆长");
        }
        User manager = userMapper.selectById(libraryAddDTO.getManagerId());
        if(manager == null){
            throw new BusinessException("未找到馆长");
        }else{
            if(manager.getRole() != 2){
                throw new BusinessException("馆长必须是管理员");
            }
        }
        // 库存没问题，添加图书馆
        Library library = new Library();
        BeanUtils.copyProperties(libraryAddDTO, library);

        boolean result = libraryMapper.insert(library) > 0;
        if (!result) {
            throw new BusinessException("添加失败");
        }
        return Result.success(library);
    }


    // 该方法给管理员使用，正常的开馆有定时任务
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result closeLibrary(LibraryCloseDTO libraryCloseDTO) {
        Library library = libraryMapper.selectById(libraryCloseDTO.getId());
        if (library == null) {
            return Result.error("未找到该图书馆");
        }
        library.setLibraryStatus(2);
        library.setEndTime(libraryCloseDTO.getEndTime());
        boolean result = libraryMapper.updateById(library) > 0;
        if (!result) {
            return Result.error("关闭图书馆失败");
        }
        return Result.success();
    }


    // 该方法给管理员使用，正常的闭馆有定时任务
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result openLibrary(Long id) {
        Library library = libraryMapper.selectById(id);
        if (library == null) {
            return Result.error("未找到该图书馆");
        }
        LocalTime now = LocalTime.now();
        Library openLibrary = new Library();
        if (now.isBefore(library.getDailyOpenTime()) || now.isAfter(library.getDailyCloseTime())){
            openLibrary.setLibraryStatus(0);
        }
        else{
            openLibrary.setLibraryStatus(1);
        }
        openLibrary.setEndTime(null);
        boolean result = libraryMapper.updateById(openLibrary) > 0;
        if (!result) {
            return Result.error("开启图书馆失败");
        }
        return Result.success();
    }

    @Override
    public Result updateLibrary(LibraryUpdateDTO libraryUpdateDTO) {
        // 先查一下库存
        Library library = libraryMapper.selectById(libraryUpdateDTO.getId());
        if (library == null) {
            return Result.error("未找到该图书馆");
        }
        // 再更新
        BeanUtils.copyProperties(libraryUpdateDTO, library);
        boolean result = libraryMapper.updateById(library) > 0;
        if (!result) {
            return Result.error("更新图书馆失败");
        }
        return Result.success(library);
    }

    @Override
    public Result deleteLibrary(Long id) {
        // 先查一下库存
        Library library = libraryMapper.selectById(id);
        if (library == null) {
            return Result.error("未找到该图书馆");
        }
        // 删除馆长
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("id", library.getManagerId());
        boolean result2 = userMapper.delete(userQueryWrapper) > 0;
        // 删除图书馆
        boolean result3 = libraryMapper.deleteById(id) > 0;
        // 删除所有房间
        QueryWrapper<Room> roomQueryWrapper = new QueryWrapper<>();
        roomQueryWrapper.eq("library_id", id);
        boolean result1 = roomMapper.delete(roomQueryWrapper) > 0;
        if (!result1 ||!result2 ||!result3) {
            return Result.error("删除图书馆失败");
        }
        return Result.success();
    }

    @Override
    public Result getLibraryBooks(Long libraryId) {
        // 先查一下库存
        Library library = libraryMapper.selectById(libraryId);
        if (library == null) {
            return Result.error("未找到该图书馆");
        }
        // 查书
        QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
        // 通过书架关联查询图书
        QueryWrapper<com.example.domain.Bookshelf> bookshelfWrapper = new QueryWrapper<>();
        QueryWrapper<Room> roomWrapper = new QueryWrapper<>();
        roomWrapper.eq("library_id", libraryId);
        List<Room> rooms = roomMapper.selectList(roomWrapper);
        
        List<Book> libraryBooks = new ArrayList<>();
        if (!rooms.isEmpty()) {
            List<Long> roomIds = rooms.stream().map(Room::getId).toList();
            bookshelfWrapper.in("room_id", roomIds);
            List<com.example.domain.Bookshelf> bookshelves = bookshelfMapper.selectList(bookshelfWrapper);
            
            if (!bookshelves.isEmpty()) {
                List<Long> bookshelfIds = bookshelves.stream().map(com.example.domain.Bookshelf::getId).toList();
                queryWrapper.in("bookshelf_id", bookshelfIds);
                libraryBooks = bookMapper.selectList(queryWrapper);
            }
        }
        return Result.success(libraryBooks);
    }

    @Override
    public Result getLibraryBookshelfs() {
        // 查询所有图书馆
        List<Library> libraries = libraryMapper.selectList(null);
        if (libraries.isEmpty()) {
            return Result.success(new ArrayList<>());
        }

        // 查询所有房间
        List<Room> allRooms = roomMapper.selectList(null);
        
        // 查询所有书架
        List<Bookshelf> allBookshelves = bookshelfMapper.selectList(null);
        
        // 使用Map优化数据分组，避免重复遍历
        Map<Long, List<Room>> libraryRoomsMap = allRooms.stream()
                .collect(Collectors.groupingBy(Room::getLibraryId));
        
        Map<Long, List<Bookshelf>> roomBookshelvesMap = allBookshelves.stream()
                .collect(Collectors.groupingBy(Bookshelf::getRoomId));
        
        // 构建嵌套结构
        List<LibraryTreeVO> libraryTrees = new ArrayList<>();
        
        for (Library library : libraries) {
            LibraryTreeVO libraryTreeVO = new LibraryTreeVO();
            BeanUtils.copyProperties(library, libraryTreeVO);
            
            // 获取该图书馆下的所有房间
            List<Room> libraryRooms = libraryRoomsMap.getOrDefault(library.getId(), new ArrayList<>());
            List<RoomTreeVO> roomTrees = new ArrayList<>();
            
            for (Room room : libraryRooms) {
                RoomTreeVO roomTreeVO = new RoomTreeVO();
                BeanUtils.copyProperties(room, roomTreeVO);
                
                // 获取该房间下的所有书架
                List<Bookshelf> roomBookshelves = roomBookshelvesMap.getOrDefault(room.getId(), new ArrayList<>());
                List<BookshelfTreeVO> bookshelfTrees = new ArrayList<>();
                
                for (Bookshelf bookshelf : roomBookshelves) {
                    BookshelfTreeVO bookshelfTreeVO = new BookshelfTreeVO();
                    // 使用书架编号作为name
                    bookshelfTreeVO.setId(bookshelf.getId());
                    bookshelfTreeVO.setName(bookshelf.getNumber());
                    bookshelfTrees.add(bookshelfTreeVO);
                }
                
                roomTreeVO.setChildren(bookshelfTrees);
                roomTrees.add(roomTreeVO);
            }
            
            libraryTreeVO.setChildren(roomTrees);
            libraryTrees.add(libraryTreeVO);
        }
        
        return Result.success(libraryTrees);
    }
}




